﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.IO;
using System.Windows;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Win32;
using System.Data.SqlClient;
using System.Data;
using System.Reflection;
using com.sanadc.shohdi.windowslink;


namespace IbnBazSetupHelper
{
    [RunInstaller(true)]
    public partial class MyInstallerHelper : System.Configuration.Install.Installer
    {
        public MyInstallerHelper()
        {
            InitializeComponent();
        }

        static double dblVersion = 0;
        protected override void OnAfterInstall(IDictionary savedState)
        {
            try
            {
                base.OnAfterInstall(savedState);
                FileInfo fileInfo = new FileInfo
                (System.Reflection.Assembly.GetExecutingAssembly().Location);
                string strZipPath = Path.Combine(fileInfo.DirectoryName, "IbnBazSetup.zip");

                //string setupPath = extractZip(strZipPath);

                //Take custom action data values
                //string sProgram = Context.Parameters["Run"];
                //string sProgram = "Setup.exe";
               // sProgram = Path.Combine(fileInfo.DirectoryName, sProgram);
                //Trace.WriteLine("Install sProgram= " + sProgram);
                //OpenWithStartInfo(sProgram);

                //FileInfo fi = new FileInfo(setupPath);

                string dataPath = Path.Combine(fileInfo.DirectoryName, "IbnBazSetup");

                if (!dataPath.Trim().EndsWith("\\"))
                    dataPath = dataPath.Trim() + "\\";

                dblVersion = ShohdiWindowsVersion.WindowsVersionClass.getWindowsVer();



                //installDotNet1(dataPath);

                //installDotNet1sp1(dataPath);

                //installcassini1(dataPath);

                restoreDatabase(dataPath);

                checkRegistryKeys(dataPath);
                //runSetupAndWait(setupPath);


                createLinks(dataPath);

            }
            catch (Exception exc)
            {
                Context.LogMessage(exc.ToString());
                throw;
            }
        }

        private void createLinks(string dataPath)
        {
            string strFile = dataPath + "source\\FatawaBaz.exe";
            string strLinkName = "فتاوى الشيخ بن باز";

            string strLinkPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
            


            ShohdiWindowsLink.createLink(strFile, strLinkPath, strLinkName);


            strLinkPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu);

            ShohdiWindowsLink.createLink(strFile, strLinkPath, strLinkName);


        }

        private void checkRegistryKeys(string dataPath)
        {

            RegistryKey rkMachine = Registry.LocalMachine;

            RegistryKey rkSoftware = rkMachine.OpenSubKey("SOFTWARE", true);

            string[] softsubKeys = rkSoftware.GetSubKeyNames();

            bool bFound = false;
            foreach (string str in softsubKeys)
                if (str.ToLower() == "Harf".ToLower())
                    bFound = true;

            if (!bFound)
                rkSoftware.CreateSubKey("Harf");

            bFound = false;

            RegistryKey rkHarf = rkSoftware.OpenSubKey("Harf", true);


           

            softsubKeys = rkHarf.GetSubKeyNames();

            foreach (string str in softsubKeys)
                if (str.ToLower() == "WebCDInit".ToLower())
                    bFound = true;

            if (!bFound)
                rkHarf.CreateSubKey("WebCDInit");


            bFound = false;



            RegistryKey rkWebCDInit = rkHarf.OpenSubKey("WebCDInit", true);

            softsubKeys = rkWebCDInit.GetSubKeyNames();

            foreach (string str in softsubKeys)
                if (str.ToLower() == "FatawaBaz".ToLower())
                    bFound = true;

            if (!bFound)
                rkWebCDInit.CreateSubKey("FatawaBaz");


            bFound = false;


            RegistryKey rkFatawaBaz = rkWebCDInit.OpenSubKey("FatawaBaz", true);

            

            rkFatawaBaz.SetValue("DefaultPage", "WebInterface\\Defualt.aspx");
            rkFatawaBaz.SetValue("Path", dataPath + "source\\Web\\");


            softsubKeys = rkWebCDInit.GetSubKeyNames();

            foreach (string str in softsubKeys)
                if (str.ToLower() == "FatawaBazService".ToLower())
                    bFound = true;

            if (!bFound)
                rkWebCDInit.CreateSubKey("FatawaBazService");


            bFound = false;


            RegistryKey rkFatawaBazService = rkWebCDInit.OpenSubKey("FatawaBazService", true);

            rkFatawaBazService.SetValue("Path", dataPath + "source\\Web\\WebService1\\");


            rkFatawaBaz.Close();
            rkFatawaBazService.Close();

            rkWebCDInit.Close();
            rkHarf.Close();
            rkSoftware.Close();
            

        }

        

        private void installcassini1(string dataPath)
        {
            string mainPath1 = dataPath + "source\\";
            string strFile = mainPath1 + "Cassini1.exe";

            Process prNew = new Process();
            ProcessStartInfo psi = new ProcessStartInfo(strFile);
            psi.UseShellExecute = true;
            if (dblVersion >= 5.2)
            {
                psi.Verb = "runas";
            }
            psi.Arguments = "/quiet";

            prNew.StartInfo = psi;
            prNew.Start();
            prNew.WaitForExit();
        }

        private void installDotNet1sp1(string dataPath)
        {
            string mainPath1 = dataPath + "source\\";
            string strFile = mainPath1 + "dotnetfxsp1.exe";

            Process prNew = new Process();
            ProcessStartInfo psi = new ProcessStartInfo(strFile);
            psi.UseShellExecute = true;
            if (dblVersion >= 5.2)
            {
                psi.Verb = "runas";
            }

            psi.Arguments = "/Q";
            prNew.StartInfo = psi;
            prNew.Start();
            prNew.WaitForExit();
        }

        private void installDotNet1(string dataPath)
        {
            string mainPath1 = dataPath + "source\\";
            string strFile = mainPath1 + "dotnetfx.exe";

            Process prNew = new Process();
            ProcessStartInfo psi = new ProcessStartInfo(strFile);
            psi.UseShellExecute = true;
            if (dblVersion >= 5.2)
            {
                psi.Verb = "runas";
            }

            psi.Arguments = "/Q";

            prNew.StartInfo = psi;
            prNew.Start();
            prNew.WaitForExit();
            
        }

        string serverName = ".";

        private void getInstalledInstance()
        {
            


            FileInfo fi = new FileInfo(Assembly.GetExecutingAssembly().Location);
            string dir = fi.DirectoryName;
            if (!dir.EndsWith("\\"))
                dir += "\\";



            string exeName = dir + "IbnBazSQL.exe";


            Process prNew = new Process();
            ProcessStartInfo psi = new ProcessStartInfo(exeName);
            psi.UseShellExecute = true;
            if (dblVersion >= 5.2)
            {
                psi.Verb = "runas";
            }

           
            prNew.StartInfo = psi;

            string txtName = dir + "SqlIns.txt";

            if (!File.Exists(txtName))
            {
                prNew.Start();
                prNew.WaitForExit();
            }


            

            string[] str = new string[0];

            try
            {
                str = File.ReadAllLines(txtName);
            }
            catch
            {
                serverName = ".\\SQLEXPRESS";
                return;
            }



            if (str.Length == 0)
            {
                serverName = ".\\SQLEXPRESS";
                return;
            }


            foreach (string strIn in str)
            {
                if (strIn == ".\\SQLEXPRESS")
                {
                    serverName = strIn;
                    return;
                }
            }

            serverName = str[0];





        }

        string mainPath = "";

        private void restoreDatabase(string dataPath)
        {
            mainPath = dataPath + "source\\";
            


            getInstalledInstance();


            checkDataBaseAndRestoreIfNotFound();
        }


        private void checkDataBaseAndRestoreIfNotFound()
        {
            bool dataCheck = checkDBExistence();
            if (!dataCheck)
            {
                createDataBase();
            }
        }

        private void createDataBase()
        {
            FileInfo FileName = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string strDir = mainPath;

            string strDBFile = strDir + "AlIftaaGateDBIbnBaz.bak";

            string conn = "Data Source=" + serverName + ";Initial Catalog=master;Integrated Security=True";

            string dbNewLocation = Environment.SystemDirectory.Substring(0, 3);

            dbNewLocation = dbNewLocation + "IbnBazDB\\";
            if (!Directory.Exists(dbNewLocation))
                Directory.CreateDirectory(dbNewLocation);



            SqlConnection sqlConn = new SqlConnection(conn);

            try
            {
                if (sqlConn.State != ConnectionState.Open)
                    sqlConn.Open();



                string createDBSQL = "IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'AlIftaaGateDBIbnBaz') " +
                                    "BEGIN " +
                                    "CREATE DATABASE [AlIftaaGateDBIbnBaz] ON  PRIMARY " +
                                    "( NAME = N'AlIftaaGateDBIbnBaz', FILENAME = N'" + dbNewLocation + "AlIftaaGateDBIbnBaz.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) " +
                                    " LOG ON  " +
                                    "( NAME = N'AlIftaaGateDBIbnBaz_log', FILENAME = N'" + dbNewLocation + "AlIftaaGateDBIbnBaz.LDF' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) " +
                                    "END ";
                string restoreSQL = "RESTORE DATABASE [AlIftaaGateDBIbnBaz] FROM  DISK = N'" + strDBFile + "' WITH  FILE = 1," +
                                     "NOUNLOAD,  REPLACE,  STATS = 10";

               


                SqlCommand sqlCreate = new SqlCommand(createDBSQL, sqlConn);
                sqlCreate.CommandTimeout = 900;
                sqlCreate.ExecuteNonQuery();


                SqlCommand sqlNewComm = new SqlCommand(restoreSQL, sqlConn);
                sqlNewComm.CommandTimeout = 900;
                sqlNewComm.ExecuteNonQuery();





                sqlConn.Close();


                

            }
            catch (Exception ex)
            {
                MessageBox.Show("خطأ لا يمكن تركيب الداتابيس!" + "\r\n" + ex.ToString());
                //Environment.Exit(0);

            }
            finally
            {
                if (sqlConn.State == ConnectionState.Open)
                    sqlConn.Close();
            }

        }



        private bool checkDBExistence()
        {
            string conn = "Data Source=" + serverName + ";Initial Catalog=AlIftaaGateDBIbnBaz;Integrated Security=True";

            SqlConnection sqlConn = new SqlConnection(conn);

            try
            {
                if (sqlConn.State != ConnectionState.Open)
                    sqlConn.Open();


                SqlCommand scmd = new SqlCommand("select * from Page where 1<>1 ;", sqlConn);

                SqlDataAdapter sda = new SqlDataAdapter(scmd);
                DataTable dtRet = new DataTable();
                sda.Fill(dtRet);

                sqlConn.Close();

                if (dtRet.Columns["DisplayContent"] == null)
                    return false;
                else
                    return true;




            }
            catch
            {
                return false;
            }
            finally
            {
                if (sqlConn.State == ConnectionState.Open)
                    sqlConn.Close();
            }



        }



        private static void runSetupAndWait(string setupPath)
        {
            Process p = new Process();
            ProcessStartInfo psi = new ProcessStartInfo();
            //MessageBox.Show(sProgram);
            psi.FileName = setupPath;
            if (dblVersion >= 5.2)
            {
                psi.Verb = "runas";
            }
            psi.UseShellExecute = true;
            p.StartInfo = psi;


            p.Start();
            p.WaitForExit();
        }

        private string extractZip(string strZipPath)
        {
            FileInfo fi = new FileInfo(strZipPath);
            FastZip fz = new FastZip();
            string strDir = Path.Combine(fi.DirectoryName, fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length));


            
            
            
            

            fz.ExtractZip(strZipPath, fi.DirectoryName,"");

            

            if (File.Exists(Path.Combine(strDir, "setup.exe")))
                return Path.Combine(strDir, "setup.exe");



            return "";




        }


        void OpenWithStartInfo(string sProgram)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(sProgram);
            startInfo.WindowStyle = ProcessWindowStyle.Normal;
            string[] ExcludeKeys = new string[] { "run", "WaitForExit" };
            startInfo.Arguments = ContextParametersToCommandArguments(Context, ExcludeKeys);
            Trace.WriteLine("run the program " + sProgram + startInfo.Arguments);
            Process p = Process.Start(startInfo);
            ShowWindow(p.MainWindowHandle, WindowShowStyle.Show); 	//otherwise it is 
            //not activated 
            SetForegroundWindow(p.MainWindowHandle);
            BringWindowToTop(p.MainWindowHandle); 	// Make sure the user will see 
            // the new window above of the setup.
            Trace.WriteLine("the program Responding= " + p.Responding);
            if ((Context.IsParameterTrue("WaitForExit")))
            {
                p.WaitForExit();// Have to hold the setup until the application is closed.
            }
        }


        public static String ContextParametersToCommandArguments
        (InstallContext context, string[] ExcludeKeys)
        {
            ExcludeKeys = ToLower(ExcludeKeys);
            StringBuilder sb = new StringBuilder();
            foreach (DictionaryEntry de in context.Parameters)
            {
                string sKey = (string)de.Key;
                bool bAdd = true;
                if (ExcludeKeys != null)
                {
                    bAdd = (Array.IndexOf(ExcludeKeys, sKey.ToLower()) < 0);
                }
                if (bAdd)
                {
                    AppendArgument(sb, sKey, (string)de.Value);
                }
            }
            return sb.ToString();
        }

        public static StringBuilder AppendArgument(StringBuilder sb, String Key, string value)
        {
            sb.Append(" /");
            sb.Append(Key);
            //Note that if value is empty string, = sign is expected, e.g."/PORT="
            if (value != null)
            {
                sb.Append("=");
                sb.Append(value);
            }
            return sb;
        }

        #region "FS library methods"
        public static string[] ToLower(string[] Strings)
        {
            if (Strings != null)
            {
                for (int i = 0; i < Strings.Length; i++)
                {
                    Strings[i] = Strings[i].ToLower();
                }
            }
            return Strings;
        }
        #endregion //"FS library methods"
        #region "showWindow"

        // http://pinvoke.net/default.aspx/user32.BringWindowToTop
        [DllImport("user32.dll")]
        static extern bool BringWindowToTop(IntPtr hWnd);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        //from http://pinvoke.net/default.aspx/user32.SwitchToThisWindow 
        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);

        /// <summary>Enumeration of the different ways of showing a window using 
        /// ShowWindow</summary>
        private enum WindowShowStyle : uint
        {
            Hide = 0,
            ShowNormal = 1,
            ShowMinimized = 2,
            ShowMaximized = 3,
            Maximize = 3,
            ShowNormalNoActivate = 4,
            Show = 5,
            Minimize = 6,
            ShowMinNoActivate = 7,
            ShowNoActivate = 8,
            Restore = 9,
            ShowDefault = 10,
            ForceMinimized = 11
        }
        #endregion
    }
}
